
import sys, cPickle, os, ConfigParser, functools as ft

from PyQt4.QtGui import (QMainWindow, QFileDialog, QMessageBox, QInputDialog, QAction, 
                         QCursor,QLabel, QToolBar, QApplication, QListView, QIcon)
from PyQt4.QtCore import pyqtSignature, SIGNAL, SLOT, QString, QVariant, QCoreApplication, Qt, QSize

from SimpleCells.Gui.Ui_SCMainWindow import Ui_SCMainWindow
from SimpleCells.Components.Table.SCTableData import SCTableData
from SimpleCells.Components.Table.SCDataAtom import SCDataAtom
from SimpleCells.Components.Table.SCTableModel import SCTableModel
from SimpleCells.Components.List.SCListModel import SCListModel
from SimpleCells.Components.Table.SCWorkspace import SCWorkspace,\
    SCTableModelReader
from SimpleCells.Components.Code.SCInterpreter import SCInterpreter
from SimpleCells.Components.Code.SCOutputHandler import SCOutputHandler, SCIOHandler
from SimpleCells.Components.Table.SCTableDelegate import SCTableDelegate
from SimpleCells.Components.List.SCListData import SCListDict
from SimpleCells.Components.List.SCListDelegate import SCListDelegate

try:
    from SimpleCells.Components.Plot.SCMatplotlib import SCFigureManagerQT, SCNavigationToolbar2QT
except ImportError:
    pass

from SimpleCells.Gui.SCFindDialog import SCFindDialog
from SimpleCells.Gui.SCTableResetDialog import SCTableResetDialog

HOMEPATH = '.'

try:
    HOMEPATH = os.environ['HOMEDRIVE']+os.environ['HOMEPATH']
except KeyError:
    pass

try:
    import dateutil
except ImportError:
    dateutil = None

class SCMainWindow(QMainWindow,Ui_SCMainWindow):
    ''''''
    def __init__(self,parent=None):
        QMainWindow.__init__(self,parent)
        self.setupUi(self)
        self.setupMisc()
        self.setupTable()
        self.setupCode()
        self.setupList()
        self.setupSession()
        self.setupWorkspace(self.tableReader,self.listDict)
        self.setupInterpreter(self.workspace)
        self.setupToolbar()
        self.setupCustomBar()
        self.setupStatus()
        self.setupRecent()
        self.updateTabs()
        self.updateTitle()
        self.setupConnections()
        self.updatePath(HOMEPATH)

    def setupMisc(self):
        self.__actionSep = QAction(self)
        self.__actionSep.setSeparator(True)
        self.__wTitle = self.windowTitle()
        
    def setupTable(self):
        self.tableModel = SCTableModel(100,20)
        self.tableReader = SCTableModelReader(self.tableModel)
        self.tableView.setModel(self.tableModel)
        self.tableView.addActions([self.actionCopy,self.actionCut,\
                                   self.actionPaste,self.actionPaste_Special,
                                   self.__actionSep])
        self.tableView.addActions(self.menuTable.actions())
        # Setting headers menu
        horizHeader = self.tableView.horizontalHeader()
        horizHeader.setContextMenuPolicy(Qt.ActionsContextMenu)
        horizHeader.addActions([self.actionTableDelete_Cols,])
        vertHeader = self.tableView.verticalHeader()
        vertHeader.setContextMenuPolicy(Qt.ActionsContextMenu)
        vertHeader.addActions([self.actionTableDelete_Rows,])
        # Other
        self.tableCodeTab.setCurrentIndex(0)
        self.__tableFileName = None
        if not dateutil:
            self.actionTableDate_Schedule.setEnabled(False)

    def setupCode(self):
        self.codeEdit.addActions([self.actionCopy,self.actionCut,\
                                   self.actionPaste,self.__actionSep])                
        self.codeEdit.addActions(self.menuCode.actions())
        self.__codeFinder = SCFindDialog(self.codeEdit,self)
        self.__codeFileName = None
        
    def setupList(self):
        self.listDict = SCListDict()
        self.listModel = SCListModel(self.listDict)
        self.listDelegate = SCListDelegate()
        self.listView.setModel(self.listModel)
        self.listView.setItemDelegate(self.listDelegate)
        self.listView.addActions(self.menuFree.actions())

    def setupSession(self):
        self.__sessionFileName = None

    def setupWorkspace(self,tableReader,listDict):
        self.workspace = SCWorkspace(tableReader,listDict)
        tableReader.model().setWorkspace(self.workspace)
        
    def setupInterpreter(self, workspace, setStreams = True):
        self.interpreter = SCInterpreter(locals=workspace)
        self.interpreter.runcode("import datetime as dt")        
        self.interpreter.runcode("from datetime import date, timedelta")
        self.interpreter.runcode("import SimpleCells.Components.Plugins as plugs")
        self.shellEdit.set_interpreter(self.interpreter)
        self.shellEdit.addActions([self.actionCopy,self.actionCut,\
                                   self.actionPaste,self.__actionSep])        
        self.shellEdit.addActions(self.menuShell.actions())
        if setStreams:
            sys.stdout = SCIOHandler('w', write_func=self.shellEdit.write, 
                                     flush_func=self.shellEdit.flush)
            sys.stderr = SCIOHandler('w', write_func=self.shellEdit.write, 
                                     flush_func= self.shellEdit.flush)            
            #sys.stdout = SCOutputHandler(self)
            #sys.stderr = SCOutputHandler(self)
        self.setupDateUtil()
        self.setupNumpy()
        self.setupMatplotlib()

    def setupDateUtil(self):
        try:
            import dateutil
            self.interpreter.runcode("import dateutil as du")
        except ImportError:
            pass
        
    def setupNumpy(self):
        try:
            import numpy
            self.interpreter.runcode("import numpy as np")
            self.interpreter.runcode("from numpy import array")
        except ImportError:
            pass
        
    def setupMatplotlib(self):
        try:
            from matplotlib import rcParams
            rcParams["interactive"]=True # interactive mode
            rcParams["backend"]="Qt4Agg" # using Qt4 to render figures
            from matplotlib.backends import backend_qt4
            backend_qt4.FigureManagerQT = SCFigureManagerQT
            backend_qt4.NavigationToolbar2QT = SCNavigationToolbar2QT
            self.interpreter.runcode("import pylab as pl")
            self.interpreter.runcode("from SimpleCells.Components.Plot.SCMatplotlib import plot3d")
        except ImportError:
            pass

    def setupStatus(self):
        self.statusLabel = QLabel(self)
        self.statusbar.addPermanentWidget(self.statusLabel)
        
    def setupToolbar(self):
        '''Setting main toolbar'''
        self.toolBar.addAction(self.actionSessionOpen)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.actionCodeRun)
    
    def setupCustomBar(self):
        ''''''
        # Custom toolbar
        self.customBar = QToolBar(self)
        self.customBar.setObjectName("customBar")
        self.customBar.setWindowTitle(QApplication.translate("SCMainWindow", "customBar", 
                                                             None, QApplication.UnicodeUTF8))
        self.customBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        #self.customBar.setIconSize(QSize(8,8))
        self.addToolBar(Qt.TopToolBarArea, self.customBar)
        self.__customActions = []

    def setupRecent(self):
        self.__recentFileIni = os.path.join(HOMEPATH,'.simplecells')
        self.__maxRecents = 10
        self.recentFilesAct = []
        self.menuFile.addSeparator()
        if os.path.isfile(self.__recentFileIni):
            f = open(self.__recentFileIni,'r')
            lines = f.readlines()
            f.close()
            for line in (line.strip() for line in lines if line.strip()):
                if not os.path.isfile(line): continue
                self.recentFilesAct.append(QAction(line,self))
                self.recentFilesAct[-1].setData(QVariant(line))
                self.connect(self.recentFilesAct[-1],SIGNAL("triggered()"),self,SLOT("openRecent()"))
                self.menuFile.addAction(self.recentFilesAct[-1])
        else:
            f = open(self.__recentFileIni,'wb')
            f.close()
    
    @pyqtSignature("")
    def updateRecent(self):
        if self.__sessionFileName:
            recentFiles = []
            for i, action in enumerate(self.recentFilesAct):
                name = str(action.text())
                if self.__sessionFileName == name: continue
                recentFiles.append(name)
                if i >= self.__maxRecents-1: break
            recentFiles.insert(0,os.path.abspath(self.__sessionFileName))
            f = open(self.__recentFileIni,'wb')
            for recent in recentFiles:
                f.write(recent+'\n')
            f.close()

    def setupConnections(self):
        self.connect(self.actionTableEmpty_Selection,SIGNAL("triggered()"),
                     self.tableView,SLOT("emptySelection()"))
        self.connect(self,SIGNAL("envUpdate(QString)"),self,SLOT("updateEnv(QString)"))
        self.connect(self,SIGNAL("startExecFile()"),self,SLOT("startRunning()"))
        self.connect(self,SIGNAL("endExecFile()"),self,SLOT("endRunning()"))
        self.connect(self.listDict,SIGNAL("dictChanged()"),self,SLOT("updateData()"))
        self.connect(self.tableReader,SIGNAL("tableChanged()"),self,SLOT("updateData()"))
        self.connect(self.listDelegate,SIGNAL("putOnShell(QString)"),self.shellEdit,SLOT("write(QString)"))

    @pyqtSignature("")
    def updateData(self):
        self.listModel.reset()
        self.tableModel.reset()
        
    @pyqtSignature("QString")
    def updateEnv(self,aPath):
        self.updateTabs()
        self.updatePath(aPath)
        self.updateRecent()
        self.updateTitle()
        self.updateCustomBar()

    def updatePath(self,aPath):
        self.__path = aPath
        os.chdir(str(self.__path))
            
    def updateCodeTab(self):
        if self.__codeFileName:
            baseName = os.path.basename(self.__codeFileName)#.split('.')[0]
            self.tableCodeTab.setTabText(1,"Code [%s]" % baseName)
            self.tableCodeTab.setTabToolTip(1,self.__codeFileName)
        else:
            self.tableCodeTab.setTabText(1,"Code []")
            self.tableCodeTab.setTabToolTip(1,"No file")
            
    def updateTableTab(self):
        if self.__tableFileName:
            baseName = os.path.basename(self.__tableFileName)#.split('.')[0]
            self.tableCodeTab.setTabText(0,"Table [%s]" % baseName)
            self.tableCodeTab.setTabToolTip(0,self.__tableFileName)
        else:
            self.tableCodeTab.setTabText(0,"Table []")
            self.tableCodeTab.setTabToolTip(0,"No file")
    
    def updateFreeTab(self):
        if self.__tableFileName:
            baseName = os.path.basename(self.__tableFileName)#.split('.')[0]
            self.tableCodeTab.setTabText(2,"Free [%s]" % baseName)
            self.tableCodeTab.setTabToolTip(2,self.__tableFileName)
        else:
            self.tableCodeTab.setTabText(2,"Free []")
            self.tableCodeTab.setTabToolTip(2,"No file")        

    def updateTabs(self):
        self.updateCodeTab()
        self.updateTableTab()
        self.updateFreeTab()
    
    def updateTitle(self):
        if self.__sessionFileName:
            baseName = os.path.basename(self.__sessionFileName)
            self.setWindowTitle(self.__wTitle+QString(' [%1]').arg(baseName))
        else:
            self.setWindowTitle(self.__wTitle+QString(' []'))
    
    def updateCustomBar(self):
        self.clearCustomActions()
        for name in self.workspace['__actions__']:
            self.addCustomAction(name)

    def closeEvent(self,event):
        answer = QMessageBox.question(self,'Closing','Would you like to save data before closing?',
                                QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
        if answer == QMessageBox.Yes:
            self.updateRecent()
            self.on_actionCodeSave_Source_triggered()
            self.on_actionTableSave_Data_triggered()
            self.on_actionSessionSave_triggered()
            #QCoreApplication.processEvents()
            event.accept()
        elif answer == QMessageBox.No:
            event.accept()
        else:
            event.ignore()
        
    @pyqtSignature("")
    def openRecent(self):
        pos = self.menuFile.mapFromGlobal(QCursor.pos())
        name = str(self.menuFile.actionAt(pos).data().toString())
        self.__sessionFileName = os.path.abspath(name)
        self.sessionLoader(self.__sessionFileName)
        
    @pyqtSignature("")
    def on_actionCopy_triggered(self):
        if self.focusWidget() in (self.tableView,self.codeEdit,
                                  self.shellEdit,self.listView):
            self.focusWidget().copy()

    @pyqtSignature("")
    def on_actionCopy_Special_triggered(self):
        if self.focusWidget() is self.tableView:
            self.tableView.copy(evaluate=True)
        elif self.focusWidget() in (self.codeEdit, self.shellEdit,
                                    self.listView):
            self.focusWidget().copy()

    @pyqtSignature("")
    def on_actionPaste_triggered(self):
        if self.focusWidget() in (self.tableView,self.codeEdit,
                                  self.shellEdit,self.listView):
            self.focusWidget().paste()

    @pyqtSignature("")
    def on_actionPaste_Special_triggered(self):
        if self.focusWidget() is self.tableView:
            self.tableView.paste(transpose=True)
        elif self.focusWidget() in (self.codeEdit, self.shellEdit,
                                    self.listView):
            self.focusWidget().paste()

    @pyqtSignature("")
    def on_actionCut_triggered(self):
        if self.tableCodeTab.currentWidget() is self.tableTab:
            self.tableView.cut()
        elif self.focusWidget() in (self.codeEdit, self.shellEdit,
                                    self.listView):
            self.codeEdit.cut()

    @pyqtSignature("")
    def on_actionSessionOpen_triggered(self):
        tmpFileName = QFileDialog.getOpenFileName(self,"Please insert the name of Session:",
                            self.__path,"Session data (*.scs)")
        if tmpFileName:
            self.__sessionFileName = os.path.abspath(str(tmpFileName))
            self.sessionLoader(self.__sessionFileName)
    
    def sessionReset(self):
        self.__sessionFileName = None
        self.updateTitle()
        self.codeReset()
        self.tableReset()
        self.freeReset()
        self.shellReset()
        self.updateCustomBar()

    @pyqtSignature("")
    def on_actionSessionNew_triggered(self):
        if QMessageBox.question(self,'New Session','This action will close the present session,\nwould you like to continue?',
                                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
            self.on_actionSessionSave_triggered()
            self.sessionReset()

    @pyqtSignature("")
    def on_actionSessionSave_triggered(self):
        if not self.__sessionFileName:
            return self.on_actionSessionSave_As_triggered()
        return self.sessionSaver(self.__sessionFileName)
        
    @pyqtSignature("")
    def on_actionSessionSave_As_triggered(self):
        tmpFileName = QFileDialog.getSaveFileName(self,"Please insert the name of Session:",
                            self.__path,"Session data (*.scs)")
        if tmpFileName:
            self.__sessionFileName = os.path.abspath(str(tmpFileName))
            return self.sessionSaver(self.__sessionFileName)

    def sessionLoader(self,sessionFileName):
        try:
            session = ConfigParser.ConfigParser()
            session.readfp(open(sessionFileName,'r'))
            dirName = os.path.dirname(sessionFileName)
            if not session.get('FILES','tablefile') == 'None':
                relName = os.path.relpath(session.get('FILES','tablefile'))
                tableFileName = os.path.join(dirName,relName)
                self.tableLoader(tableFileName)
                self.__tableFileName = tableFileName
            if not session.get('FILES','codefile') == 'None':
                relName = os.path.relpath(session.get('FILES','codefile'))
                codeFileName = os.path.join(dirName,relName)
                self.codeLoader(codeFileName)
                self.__codeFileName = codeFileName
            self.on_actionShellReset_Workspace_triggered()
            self.emit(SIGNAL("envUpdate(QString)"),QString(dirName))
        except IOError:
            self.__sessionFileName = None

    def sessionSaver(self,sessionFileName):
        session = ConfigParser.ConfigParser()
        session.add_section('FILES')
        dirName = os.path.dirname(sessionFileName)
        if self.__tableFileName:
            session.set('FILES','tablefile',os.path.relpath(self.__tableFileName,dirName))
        else:
            session.set('FILES','tablefile','None')
        if self.__codeFileName:
            session.set('FILES','codefile',os.path.relpath(self.__codeFileName,dirName))
        else:
            session.set('FILES','codefile','None')
        session.write(open(sessionFileName,'wb'))
        self.emit(SIGNAL("envUpdate(QString)"),QString(os.path.dirname(sessionFileName)))
    
    @pyqtSignature("")
    def on_actionAbout_triggered(self):
        QMessageBox.about(self,"About SimpleCells","SimpleCells is one table, one code and one shell.\n\nemail: alex [dot] radi [at] gmail [dot] com")
    
    @pyqtSignature("")
    def on_actionFind_triggered(self):
        if self.tableCodeTab.currentWidget() is self.tableTab:
            pass
        elif self.tableCodeTab.currentWidget() is self.codeTab:
            self.__codeFinder.exec_()

    # Code
    
    @pyqtSignature("")
    def on_actionCodeLoad_Source_triggered(self):
        self.tableCodeTab.setCurrentIndex(1)
        tmpFileName = QFileDialog.getOpenFileName(self,"Please insert the name of Code:",
                            self.__path,"Python code (*.py *.pyw)")
        if tmpFileName:
            self.__codeFileName = os.path.abspath(str(tmpFileName))
            self.codeLoader(self.__codeFileName)

    @pyqtSignature("")
    def on_actionCodeSave_Source_triggered(self):
        if not self.__codeFileName:
            return self.on_actionCodeSave_Source_As_triggered()
        return self.codeSaver(self.__codeFileName)

    @pyqtSignature("")
    def on_actionCodeSave_Source_As_triggered(self):
        tmpFileName = QFileDialog.getSaveFileName(self,"Please insert the name of Code:",
                            self.__path,"Python code (*.py *.pyw)")
        if tmpFileName:
            self.__codeFileName = os.path.abspath(str(tmpFileName))
            return self.codeSaver(self.__codeFileName)

    @pyqtSignature("")
    def on_actionCodeRun_triggered(self):
        #self.tableCodeTab.setCurrentIndex(1)
        if not self.__codeFileName:
            self.on_actionCodeSave_Source_As_triggered()
        else:
            self.codeSaver(self.__codeFileName)
        if not self.__codeFileName:
            return
        cmd = 'execfile(%s)' % repr(self.__codeFileName)
        self.shellEdit.write(cmd+'\n')
        self.emit(SIGNAL("startExecFile()"))
        self.shellEdit.run_command(cmd)
        self.emit(SIGNAL("endExecFile()"))

    @pyqtSignature("")
    def on_actionCodeRefresh_Actions_triggered(self):
        self.updateCustomBar()

    def codeReset(self):
        self.__codeFileName = None
        self.codeEdit.clear() 
        self.updateTabs()

    @pyqtSignature("")
    def on_actionCodeNew_Source_triggered(self):
        if QMessageBox.question(self,'Emptying','This action will close the present source file,\nwould you like to continue?',
                                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
            self.on_actionCodeSave_Source_triggered()
            self.codeReset()
    
    def codeLoader(self,codeFileName):
        try:
            f = open(codeFileName,'r')
            self.codeEdit.setText(''.join(f.readlines()))
            f.close()
            self.statusbar.showMessage(codeFileName+' Loaded.',5000)
            self.emit(SIGNAL("envUpdate(QString)"),QString(os.path.dirname(codeFileName)))
        except IOError:
            self.__codeFileName = None
                            
    def codeSaver(self,codeFileName):
        f = open(codeFileName,'wb')
        f.write(str(self.codeEdit.text()))
        f.close()
        self.statusbar.showMessage(codeFileName+' Saved.',5000)
        self.emit(SIGNAL("envUpdate(QString)"),QString(os.path.dirname(codeFileName)))

    # Table
    
    def tableReset(self):
        self.__tableFileName = None
        self.tableModel.clearAll() 
        self.updateTabs()
                    
    @pyqtSignature("")
    def on_actionTableNew_Data_triggered(self):
        if QMessageBox.question(self,'Emptying','This action will close the present table,\nwould you like to continue?',
                                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
            self.on_actionTableSave_Data_triggered()
            self.tableReset()
    
    @pyqtSignature("")
    def on_actionTableEmpty_Table_triggered(self):
        if QMessageBox.question(self,'Emptying','This action will delete all the table data,\nwould you like to continue?',
                                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
            self.tableModel.clearAll()

    @pyqtSignature("")
    def on_actionTableLoad_Data_triggered(self):
        self.tableCodeTab.setCurrentIndex(0)
        tmpFileName = QFileDialog.getOpenFileName(self,"Please insert the name of Table data:",
                            self.__path,"Table data (*.scrd)")
        if tmpFileName:
            self.__tableFileName = os.path.abspath(str(tmpFileName))
            self.tableLoader(self.__tableFileName)
    
    @pyqtSignature("")
    def on_actionTableSave_Data_triggered(self):
        if not self.__tableFileName:
            return self.on_actionTableSave_Data_As_triggered()
        return self.tableSaver(self.__tableFileName)

    @pyqtSignature("")
    def on_actionTableSave_Data_As_triggered(self):
        tmpFileName = QFileDialog.getSaveFileName(self,"Please insert the name of Table data:",
                           self.__path,"Table data (*.scrd)")
        if tmpFileName:
            self.__tableFileName = os.path.abspath(str(tmpFileName))
            return self.tableSaver(self.__tableFileName)
    
    @pyqtSignature("")
    def on_actionTableExport_to_Dict_triggered(self):
        tmpFileName = QFileDialog.getSaveFileName(self,"Please insert the name of pickled data:",
                           self.__path,"Pickle data (*.pickle)")
        if tmpFileName:
            fName = os.path.abspath(tmpFileName)
            cPickle.dump(self.tableReader.toDict(),open(fName,'w'))

    @pyqtSignature("")
    def on_actionTableAdd_Rows_triggered(self):
        self.tableCodeTab.setCurrentIndex(0)
        rows, ok = QInputDialog.getInt(self,"Add new rows","Set the number of rows to add:",0,0)
        if ok and rows > 0:
            self.tableView.addRows(rows)
    
    @pyqtSignature("")
    def on_actionTableDelete_Rows_triggered(self):
        self.tableView.deleteSelectedRows()

    @pyqtSignature("")
    def on_actionTableAdd_Cols_triggered(self):
        self.tableCodeTab.setCurrentIndex(0)
        cols, ok = QInputDialog.getInt(self,"Add new columns","Set the number of columns to add:",0,0)
        if ok and cols > 0:
            self.tableView.addColumns(cols)

    @pyqtSignature("")
    def on_actionTableDelete_Cols_triggered(self):
        self.tableView.deleteSelectedCols()

    @pyqtSignature("")
    def on_actionTableReset_Table_triggered(self):
        self.tableCodeTab.setCurrentIndex(0)
        dlg = SCTableResetDialog(100, 20, self)
        if dlg.exec_():
            if QMessageBox.question(self,'Table Reset','This action will delete all the table data,\nwould you like to continue?',
                                    QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
                self.tableView.resetAll(dlg.rows, dlg.cols)

    @pyqtSignature("")
    def on_actionTableGenerate_triggered(self):
        self.tableView.generateValues('firstTwo')
    
    @pyqtSignature("")
    def on_actionTableFill_In_triggered(self):
        self.tableView.generateValues('firstLast')
    
    @pyqtSignature("")
    def on_actionTableRepeat_First_triggered(self):
        self.tableView.generateValues('repeatFirst')
    
    @pyqtSignature("")
    def on_actionTableConvert_Float_triggered(self):
        self.tableView.convertSelection('float')
    
    @pyqtSignature("")
    def on_actionTableConvert_Int_triggered(self):
        self.tableView.convertSelection('int')

    @pyqtSignature("")
    def on_actionTableDate_Schedule_triggered(self):
        self.tableView.generateDates()

    @pyqtSignature("")
    def on_actionTableToday_triggered(self):
        self.tableView.insertToday()

    def tableLoader(self,tableFileName):
        assert not tableFileName.endswith('.sctd'), \
            'Old table data format (sctd) not supported.'
        try:
            f = open(tableFileName,'r')
            vars = cPickle.load(f)
            tableData = SCTableData()
            tableData.setRawTable(vars['rawTableData'])
            self.tableModel.setTableData(tableData,vars['labels'])
            try:
                self.workspace['free'].setData(vars['free'])
            except KeyError:
                self.workspace['free'].setData({})
            f.close()
            self.statusbar.showMessage(tableFileName+' Loaded.',5000)
            self.emit(SIGNAL("envUpdate(QString)"),QString(os.path.dirname(tableFileName)))
        except IOError:
            self.__tableFileName = None

    def oldTableLoader(self,tableFileName):
        try:
            f = open(tableFileName,'r')
            vars = cPickle.load(f)
            tableData = vars['tableData']
            rawData = []
            for i in range(tableData.nRows()):
                rawData.append([])
                for j in range(tableData.nCols()):
                    oldAtom = tableData(i,j)
                    rawVal = oldAtom.data
                    if oldAtom.imLabel():
                        rawVal = SCDataAtom.INV_LABELS_ID[oldAtom.direction]+oldAtom.data
                        try:
                            if oldAtom.shapeHint:
                                rawVal += SCDataAtom.HINT_CHAR+oldAtom.shapeHint
                        except AttributeError:
                            pass
                    rawData[-1].append(rawVal)
            tableData = SCTableData()
            tableData.setRawTable(rawData)
            self.tableModel.setTableData(tableData, vars['labels'])
            try:
                self.workspace['free'].setData(vars['free'])
            except KeyError:
                self.workspace['free'].setData({})
            f.close()
            self.statusbar.showMessage(tableFileName+' Loaded.',5000)
            self.emit(SIGNAL("envUpdate(QString)"),QString(os.path.dirname(tableFileName)))            
        except IOError:
            self.__tableFileName = None

    def tableSaver(self,tableFileName):
        f = open(tableFileName,'wb')
        data = {}
        data['rawTableData'] = self.tableModel.getTableData().getRawTable()
        data['labels'] = self.tableModel.labels()
        data['free'] = self.workspace['free'].getData()
        cPickle.dump(data,f)
        f.close()
        self.statusbar.showMessage(tableFileName+' Saved.',5000)
        self.emit(SIGNAL("envUpdate(QString)"),QString(os.path.dirname(tableFileName)))

    # Free
    
    def freeReset(self):
        self.listView.deleteAll()

    @pyqtSignature("")
    def on_actionFreeDelete_All_triggered(self):
        if QMessageBox.question(self,'Delete All','This action will delete all this workspace data,\nwould you like to continue?',
                                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
            self.listView.deleteAll()
    
    @pyqtSignature("")
    def on_actionFreeDelete_Selected_triggered(self):
        self.listView.deleteSelected()

    @pyqtSignature("")
    def on_actionFree_AsList_triggered(self):
        self.listView.setViewMode(QListView.ListMode)
        
    @pyqtSignature("")
    def on_actionFree_AsIcons_triggered(self):
        self.listView.setViewMode(QListView.IconMode)

    # Shell

    @pyqtSignature("")
    def on_actionShellClear_Buffer_triggered(self):
        self.shellEdit.reset()

    def shellReset(self):
        self.setupWorkspace(self.tableReader,self.listDict)
        self.setupInterpreter(self.workspace,False)
        self.on_actionShellClear_Buffer_triggered()
        
    @pyqtSignature("")
    def on_actionShellReset_Workspace_triggered(self):
        self.shellReset()

    # File Running
    
    @pyqtSignature("")
    def startRunning(self):
        #self.showMinimized()
        self.clearCustomActions()
        self.setWindowTitle('Busy...')
        self.statusbar.showMessage('Please wait while computing.')
        self.statusLabel.setText('Busy...')
        QCoreApplication.processEvents()

    @pyqtSignature("")
    def endRunning(self):
        #self.showNormal()
        self.updateCustomBar()
        self.updateTitle()
        #self.setWindowTitle(self.__wTitle)
        self.statusbar.showMessage('Computation done.',5000)
        self.statusLabel.clear()
        self.activateWindow()
        self.tableModel.reset()
        #QMessageBox.information(self,"Computation","Computation ended.", \
        #                        QMessageBox.Ok)

    def addCustomAction(self,name):
        name = name.split(':')
        self.__customActions.append((QAction(QIcon(":/Icons/Actions/custom-run.svg"),
                                             name[0],self),name[-1]))
        funName = name[-1].split('(')[0]
        funDoc = self.workspace[funName].__doc__
        if funDoc: 
            self.__customActions[-1][0].setToolTip(name[-1]+'\n\n'+funDoc)
        else:
            self.__customActions[-1][0].setToolTip(name[-1])
        self.customBar.addAction(self.__customActions[-1][0])
        self.connect(self.__customActions[-1][0],SIGNAL("triggered()"),\
                     ft.partial(self.evalCustomAction,self.__customActions[-1][-1]))

    @pyqtSignature("")
    def clearCustomActions(self):
        self.customBar.clear()
        self.__customActions = []
    
    def evalCustomAction(self,instruction):
        cmd = instruction
        self.shellEdit.write(cmd+'\n')
        self.shellEdit.run_command(cmd)

def launchSimpleCells():
    import time
    from PyQt4.QtGui import QApplication, QSplashScreen, QPixmap, QColor
    from PyQt4.QtCore import Qt
    app = QApplication(sys.argv)
    splash = QSplashScreen(QPixmap(":/Splash/SplashScreenFoam.png"))
    splash.showMessage("Loading environment...", Qt.AlignBottom | Qt.AlignLeft | 
                                Qt.AlignAbsolute, QColor(Qt.white))
    splash.show()
    app.processEvents()
    time.sleep(1)
    mainWindow = SCMainWindow()
    mainWindow.show()
    splash.finish(mainWindow)
    sys.exit(app.exec_())

if __name__ == "__main__":
    launchSimpleCells()
